-
Notifications
You must be signed in to change notification settings - Fork 308
Conversation
Alright, the goal on this PR is to keep the Python API exactly the same, but have a record of email verifications in the database that is persistent across a) email removal/re-add, and b) account close/re-open. Here is the relevant API I find: class Emails(object): # gratipay.models.package.emails
def classify_emails_for_participant(self, participant): pass
class Participant(object): # gratipay.models.participant
def clear_personal_information(self, cursor): pass
class Email(object): # gratipay.models.participant.email
def start_email_verification(self, email, *packages): pass
def validate_email_verification_request(self, c, email, *packages): pass
def get_email_verification_link(self, c, email, *packages): pass
def get_email_verification_nonce(self, c, email): pass
def set_primary_email(self, email, cursor=None): pass
def _set_primary_email(self, email, cursor): pass
def finish_email_verification(self, email, nonce): pass
def save_email_address(self, cursor, address): pass
def get_email(self, address, cursor=None, and_lock=False): pass
def get_emails(self, cursor=None): pass
def get_verified_email_addresses(self, cursor=None): pass
def remove_email(self, address): pass
def set_email_lang(self, accept_lang): pass
class Packages(object): # gratipay.models.participant.packages
def get_packages_for_claiming(self, manager): pass
def start_package_claims(self, c, nonce, *packages): pass
def get_packages_claiming(self, cursor, nonce): pass
def finish_package_claims(self, cursor, nonce, *packages): pass |
Here are the places we delete from
|
DELETE FROM email_addresses WHERE participant_id = %(participant_id)s; |
take_over
gratipay.com/gratipay/models/participant/__init__.py
Lines 1113 to 1115 in e45ba2b
DELETE FROM email_addresses | |
WHERE participant_id IN (%(dead)s, %(live)s) | |
AND id NOT IN (SELECT id FROM email_addresses_to_keep); |
remove_email
gratipay.com/gratipay/models/participant/email.py
Lines 363 to 364 in e45ba2b
c.run("DELETE FROM email_addresses WHERE participant_id=%s AND address=%s", | |
(self.id, address)) |
save_email_address
gratipay.com/gratipay/models/participant/email.py
Lines 310 to 313 in e45ba2b
DELETE | |
FROM email_addresses | |
WHERE participant_id != %s | |
AND address=%s |
So basically we need to remove those |
Here are the readers: class Emails(object): # gratipay.models.package.emails
def classify_emails_for_participant(self, participant): pass
class Email(object): # gratipay.models.participant.email
def validate_email_verification_request(self, c, email, *packages): pass
def get_email_verification_nonce(self, c, email): pass
def save_email_address(self, cursor, address): pass
def get_email(self, address, cursor=None, and_lock=False): pass
def get_emails(self, cursor=None): pass
class Packages(object): # gratipay.models.participant.packages
def get_packages_for_claiming(self, manager): pass |
This is reminiscent of the schema design we use on |
Maybe a null CREATE TABLE email_addresses
( id serial PRIMARY KEY
, address text NOT NULL
, verified boolean DEFAULT NULL
CONSTRAINT verified_cant_be_false -- Only use TRUE and NULL, so that the
-- unique constraint below functions
-- properly.
CHECK (verified IS NOT FALSE)
, nonce text
, verification_start timestamp with time zone NOT NULL
DEFAULT CURRENT_TIMESTAMP
, verification_end timestamp with time zone
, participant_id bigint NOT NULL
REFERENCES participants(id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
, UNIQUE (address, verified) -- A verified email address can't be linked to multiple
-- participants. However, an *un*verified address *can*
-- be linked to multiple participants. We implement this
-- by using NULL instead of FALSE for the unverified
-- state, hence the check constraint on verified.
, UNIQUE (participant_id, address)
, CONSTRAINT emails_nonce_key UNIQUE (nonce)
); |
I think we can get rid of |
... but that also sounds like probable scope creep. |
Okay! Time to hack! 🕶️ |
Over at #4571 (comment) I think I discovered that we should be able to do this with minimal schema changes. Closing in favor of #4579. |
←
Persist email messages(#4572) — Limit pending email verifications (#4571) →Todo
DELETE
intoINSERT
.SELECT
to pull latest only.